#ifndef __tenacitas_log__thread_id__h__
#define __tenacitas_log__thread_id__h__



/** @file */


/** @todo */

// ==> C++ Headers
#include <thread>
#include <functional>

// ==> 3rds Headers

// ==> Our Headers

// ==> Namespaces
using namespace std;

// ==> Macro Constants

// ==> Macro Commands


/** ==> namespace of the organization */
namespace tenacitas {
    /** ==> namespace for the project */
    namespace log {

        // ==> Typedefs
        
        // ==> Pre-Declarations

        // ==> Attributes 

        // ==> Functions

        // ==> Classes

        /** 

            @nosubgrouping 
        */
        class thread_id {

            // ==> thread_id - Friends

            /** Class allowed to access private members of @p thread_id, in order
                to perform tests */
            friend class thread_id_tester;

            /** Outout operator */
            friend ostream & operator <<(ostream & p_out,
                                         const thread_id & p_th){
                p_out << p_th.m_value;
                return p_out;
            }
            
                

        public:

            // ==> thread_id - Public Internal Types

            // ==> thread_id - Public Constructors

            /** Default constructor

                The value id is defined from the current thread
            */
            thread_id();

            /** copy constructor  */
            thread_id (const thread_id & p_th);

            /** move constructor */
            thread_id(thread_id && p_th);

            /** Destructor */
            ~thread_id( );

            // ==> thread_id - Public Accessors

            // ==> thread_id - Public Helpers

            // ==> thread_id - Public Processors

            // ==> thread_id - Public Operators

            /** equal-to */
            bool operator ==(const thread_id & p_th) const;

            /** not-equal-to */
            bool operator !=(const thread_id & p_th) const;

            /** greater-than */
            bool operator >(const thread_id & p_th) const;

            /** less-than */
            bool operator <(const thread_id & p_th) const;

            /** copy assignment */
            thread_id & operator = (const thread_id & p_th);

            /** move assignment */
            thread_id & operator = (thread_id && p_th);
            
            /** converter */
            
            // ==> thread_id - Public Attributes

        private:

            // ==> thread_id - Private Internal Types

            // ==> thread_id - Private Constructors

            // ==> thread_id - Private Accessors

            // ==> thread_id - Private Helpers

            // ==> thread_id - Private Processors

            // ==> thread_id - Private Operators

            // ==> thread_id - Private Attributes

            /** The actual value of the id */
            std::hash<std::thread::id>::result_type m_value;
        };
    }
}

// =============================================================================
// I M P L E M E N T A T I O N
// =============================================================================

using namespace tenacitas::log;

// -----------------------------------------------------------------------------
inline thread_id::
thread_id() 
    : m_value(std::hash<std::thread::id>()(std::this_thread::get_id())){}

// -----------------------------------------------------------------------------
inline thread_id::
thread_id (const thread_id & p_th)
    :m_value(p_th.m_value){}

// -----------------------------------------------------------------------------
inline thread_id::
thread_id(thread_id && p_th) 
    :m_value(std::move(p_th.m_value)){}

// -----------------------------------------------------------------------------
inline thread_id::
~thread_id( ){m_value = std::hash<std::thread::id>()(thread::id());}//::result_type();}

// -----------------------------------------------------------------------------
inline bool
thread_id::
operator ==(const thread_id & p_th) const {return m_value == p_th.m_value;}

// -----------------------------------------------------------------------------
inline bool
thread_id::
operator !=(const thread_id & p_th) const {return m_value != p_th.m_value;}

// -----------------------------------------------------------------------------
inline bool
thread_id::
operator >(const thread_id & p_th) const {return m_value > p_th.m_value;}

// -----------------------------------------------------------------------------
inline bool
thread_id::
operator <(const thread_id & p_th) const{return m_value < p_th.m_value;}


// -----------------------------------------------------------------------------
inline thread_id &
thread_id::
operator = (const thread_id & p_th) {
    if (this != &p_th){
        m_value = p_th.m_value;
    }
    return *this;
}



// -----------------------------------------------------------------------------
inline thread_id &
thread_id::
operator = (thread_id && p_th) {
    if (this != &p_th){
        m_value = std::move(p_th.m_value);
    }
    return *this;
}


#endif
